<template>
<div class="validate-input-container pb-3 position-relative">
  <input
    v-if="tag !== 'textarea'"
    class="form-control"
    :class="{'is-invalid': inputRef.error }"
    v-model="inputRef.val"
    @blur="validateInput"
    v-bind="$attrs"
  />
  <textarea
    v-else
    class="form-control"
    v-model="inputRef.val"
    :class="{'is-invalid': inputRef.error }"
    @blur="validateInput"
    v-bind="$attrs"
  />
  <span class="invalid-feedback" v-if="inputRef.error">{{ inputRef.message }}</span>
</div>
</template>

<script lang="ts">
import { defineComponent, onMounted, PropType, reactive, computed } from 'vue'
import { emitter } from './ValidateForm.vue'
interface PropsRule {
  type: 'required' | 'email' | 'password' | 'custom';
  message: string;
  validator?: () => boolean;
}
export type ruleProps = PropsRule[];
type tagProps = 'input' | 'textarea'
export default defineComponent({
  name: 'ValidateInput',
  props: {
    rules: Array as PropType<ruleProps>,
    modelValue: String,
    tag: {
      type: String as PropType<tagProps>,
      default: 'input'
    }
  },
  setup (props, ctx) {
    const inputRef = reactive({
      val: computed({
        get: () => props.modelValue || '',
        set: val => {
          ctx.emit('update:modelValue', val)
        }
      }),
      error: false,
      message: ''
    })
    const emailReg = /^([a-zA-Z]|[0-9])(\w|-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
    const validateInput = () => {
      if (props.rules) {
        const allPassed = props.rules.every(item => {
          let passed = false
          inputRef.message = item.message
          switch (item.type) {
            case 'required':
              passed = inputRef.val.trim() !== ''
              break
            case 'email':
              passed = emailReg.test(inputRef.val)
              break
            case 'password':
              passed = inputRef.val.trim().length > 5 && inputRef.val.trim().length < 17
              break
            case 'custom':
              passed = item.validator ? item.validator() : true
              break
            default:
              break
          }
          return passed
        })
        inputRef.error = !allPassed
        return allPassed
      }
      return true
    }
    onMounted(() => {
      emitter.emit('form-item-create', validateInput)
    })
    return {
      inputRef,
      validateInput
    }
  }
})
</script>
